package logic;

import java.awt.Color;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.DefaultIndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;

public class CreateXlsx {

	/**
	 * 用于缓存单元格格式.
	 */
	private static final Map<Integer, XSSFCellStyle> CACHE = new ConcurrentHashMap<>(64000);
	
	private static List<int[]> list;
	
	private static XSSFCellStyle xstyle;
	
	/**
	 * 生成成品Excel.
	 * @param load
	 * @param path
	 * @param threads 
	 * @throws Exception
	 */
	public static void create(List<int[]> load, String path, String threads) throws Exception {
		list = load;
		int size = list.size();
		int length = list.get(0).length;

		// 先保存一个空Excel文件，在磁盘占位
		try (SXSSFWorkbook excel = new SXSSFWorkbook(size);
				FileOutputStream fos = new FileOutputStream(path)) {
			
			excel.createSheet("myPic");
			xstyle = (XSSFCellStyle) excel.createCellStyle();

			// 使用线程池进行线程管理
			int poolSize;
			try {
				poolSize = Integer.parseInt(threads, 10);
			} catch (Exception e) {
				poolSize = 12;
			}
			ExecutorService es = Executors.newFixedThreadPool(poolSize);
			// 使用计数栅栏
			CountDownLatch doneSignal = new CountDownLatch(size);

			// 读取占位的文件，设置列宽
			System.out.println("Start setting the style of cells...");
			Sheet sht = excel.getSheetAt(0);
			for (int j = 0; j < length; j++)
				sht.setColumnWidth(j, (short) 500);

			// 缓存所需的所有单元格格式
			for (int k = 0; k < size; k++)
				sht.createRow(k);

			for (int i = 0; i < size; i++) {
				es.submit(new PoiWriter(doneSignal, sht, i));
				Thread.sleep(100);
			}

			doneSignal.await();
			es.shutdown();

			excel.write(fos);
			System.out.println("Done");// 提示完成
		} catch (Exception e) {
			throw e;
		}
		
	}

	private static class PoiWriter implements Runnable {

		private final CountDownLatch doneSignal;
		private Sheet sheet;
		private int line;
		
		private static DefaultIndexedColorMap colorMap=  new DefaultIndexedColorMap();

		public PoiWriter(CountDownLatch doneSignal, Sheet sheet, int line) {
			this.doneSignal = doneSignal;
			this.sheet = sheet;
			this.line = line;
		}

		@Override
		public void run() {
			int i = line;
			try {
				int[] rgbs = list.get(i);
				Row row = sheet.getRow(i);
				
				if (row == null)
					sheet.createRow(i);
				
				try {
					row.setHeight((short) 250);
				} catch (NullPointerException e) {
					System.out.println("error:" + i);
				}

				for (int rgb : rgbs) {
					Integer key = Integer.valueOf(rgb);
					if (CACHE.get(key) == null) {
						XSSFCellStyle style = xstyle.copy();
						style.setFillForegroundColor(new XSSFColor(new Color(rgb), colorMap));
						style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
						CACHE.put(key, style);
					}
				}
				
				for (int j = 0; j < rgbs.length; j++)
					row.createCell(j).setCellStyle(CACHE.get(rgbs[j]));
				
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				doneSignal.countDown();
				System.out.println("line:" + i + " Count: " + doneSignal.getCount());
			}
		}
		
	}
	
}